package com.example.demo.common;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: DELL
 * Date: 2023-06-11
 * Time: 21:07
 */
// 密码的加盐加密工具类
public class PasswordTools {

    /**
     * 加盐加密
     *
     * @param password 用户的明明密码
     * @return 返回加盐加密后的密码
     */
    public static String encrypt(String password) {
        // 1. 产生盐值
        String salt = UUID.randomUUID().toString().replace("-", "");
        // 2. 使用 MD5 (盐值 + 明文密码) 得到加密的密码
        String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes(StandardCharsets.UTF_8));
        // 3. 将盐值以及加密后的密码一同合并返回
        return salt + "$" + finalPassword;

    }

    /**
     * 加盐加密的重载方法
     *
     * @param password 用户传入的密码 (不一定正确)
     * @param salt     传入的盐值
     * @return 返回盐值以及加盐加密后的字符串
     */
    public static String encrypt(String password, String salt) {
        // 1. 使用 MD5 (盐值 + 明文密码) 得到加密的密码
        String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes(StandardCharsets.UTF_8));
        // 2. 将盐值以及加密后的密码一同合并返回
        return salt + "$" + finalPassword;

    }

    /**
     * 解密加盐加密后的密码
     *
     * @param password   用户传入的密码 (不一定正确_
     * @param dbPassword 数据库中存储的 加盐加密后的密码和和盐值
     * @return 用户的密码是否正确
     */
    public static boolean decrypt(String password, String dbPassword) {

        boolean result = false;

        // 1. 参数验证
        if (StringUtils.hasLength(password) && StringUtils.hasLength(dbPassword) &&
                dbPassword.length() == 65 && dbPassword.contains("$")) {
            // 1.1 切割得到盐值
            String[] passwordArray = dbPassword.split("\\$");
            String salt = passwordArray[0];
            // 1.2 得到数据库中存储的正确的加盐加密的密码
            String finalPassword = passwordArray[1];

            // 2. 根据得到的盐值和原始password 密码通过上面的重载方法进行加盐加密后和 dbPassword 进行对比
            String checkPassword = encrypt(password, salt);
            if (checkPassword.equals(dbPassword)) result = true;

        }
        return result;
    }

    public static void main(String[] args) {

        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();

        String password = "123"; // 正确明文传入密码

        // 安全框架的加盐方法
        String dbPassword = bCryptPasswordEncoder.encode(password); // 加密后连同盐值存入数据库的密码
        String dbPassword2 = bCryptPasswordEncoder.encode(password);
        String dbPassword3 = bCryptPasswordEncoder.encode(password);

//        String dbPassword = PasswordTools.encrypt(password); // 加密后连同盐值存入数据库的密码
//        String dbPassword2 = PasswordTools.encrypt(password);
//        String dbPassword3 = PasswordTools.encrypt(password);

        System.out.println(dbPassword);
        System.out.println(dbPassword2);
        System.out.println(dbPassword3);

        String checkPassword = "1234"; // 传入要验证的密码 (错误的)

        boolean result = bCryptPasswordEncoder.matches(checkPassword, dbPassword3);
        System.out.println("错误密码结果: " + result);

//        boolean result = PasswordTools.decrypt(checkPassword, dbPassword3);
//        System.out.println("错误密码结果: " + result);

        // 加盐后对比验证方法
        boolean result2 = bCryptPasswordEncoder.matches(password, dbPassword2);
        System.out.println("正确密码结果: " + result2);

//        boolean result2 = PasswordTools.decrypt(password, dbPassword2);
//        System.out.println("正确密码结果: " + result2);

//        System.out.println(PasswordTools.encrypt(password));
//        System.out.println(PasswordTools.encrypt(password));
//        System.out.println(PasswordTools.encrypt(password));
    }
}
